package com.haoze.common.utils;

import com.haoze.common.dto.AgeDTO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {
    private static final Logger logger = LoggerFactory.getLogger(DateUtil.class);

    public static final   String  YYYYMMDDHHMMSS="yyyy-MM-dd HH:mm:ss";

    /**
     * String型日期转Timestamp
     * @param time
     * @return
     */
    public static Timestamp stringToTimestamp(String time) {
        return new Timestamp(DateUtil.stringToDate(time).getTime());
    }

    /**
     * Timestamp日期转String型日期
     * @param time
     * @param format
     * @return
     */
    public static String timestampToString(Timestamp time, String format) {
        String timeStr = "";
        DateFormat sdf = new SimpleDateFormat(format);
        try {
            //方法一
            timeStr = sdf.format(time);

            //方法二
//            timeStr = time.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return timeStr;
    }

    /**
     * Date型日期转Timestamp
     * @param time
     * @return
     */
    public static Timestamp dateToTimestamp(Date time) {
        return new Timestamp(time.getTime());
    }

    /**
     * Timestamp日期转Date
     * @param time
     * @return
     */
    public static Date timestampToDate(Timestamp time) {
        return time;
    }

    /**
     * Date转String型日期
     * @param time
     * @param format
     * @return
     */
    public static String dateToString(Date time, String format) {
        String timeStr = "";
        //format的格式可以任意
        DateFormat sdf = new SimpleDateFormat(format);
        try {
            timeStr = sdf.format(time);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return timeStr;
    }

    /**
     * String型日期转Date
     * @param time
     * @return
     */
    public static Date stringToDate(String time) {
        Date date = new Date();
        if (StringUtils.isBlank(time)) {
            return date;
        }
        String formatter = DateUtil.getFormatter(time.length());
        //注意format的格式要与日期String的格式相匹配
        DateFormat sdf = new SimpleDateFormat(formatter);
        try {
            date = sdf.parse(time);
        } catch (Exception e) {
            logger.error("转换时间出错", e);
        }
        return date;
    }

    /**
     * String型日期转Date
     * @param time
     * @return
     */
    public static Date stringToDate(String time, String format) {
        Date date = new Date();
        if (StringUtils.isBlank(time)) {
            return date;
        }
        //注意format的格式要与日期String的格式相匹配
        DateFormat sdf = new SimpleDateFormat(format);
        try {
            date = sdf.parse(time);
        } catch (Exception e) {
            logger.error("转换时间出错", e);
        }
        return date;
    }

    /**
     * 根据format长度返回时间格式
     * @param length
     * @return
     */
    public static String getFormatter(int length) {
        String formatter = "yyyy-MM-dd";
        if (length == 16) {
            formatter = "yyyy-MM-dd HH:mm";
        } else if (length == 19) {
            formatter = "yyyy-MM-dd HH:mm:ss";
        } else if (length == 20) {
            formatter = "yyyy-MM-dd HH:mm:ss.S";
        } else if (length == 21) {
            formatter = "yyyy-MM-dd HH:mm:ss.SS";
        } else if (length == 22) {
            formatter = "yyyy-MM-dd HH:mm:ss.SSS";
        }
        return formatter;
    }

    /**
     * 计算指定时间的之前或之后多久时间(获取目标时间-值代表之前，+值代表之后)
     * @param nodeDate 基准时间
     * @param years 年差
     * @param months 月差
     * @param days 日差
     * @param hours 时差
     * @param minutes 分差
     * @param seconds 秒差
     * @return 根据基准时间计算时差后得到的日期
     */
    public static Date getTargetDate(Date nodeDate, int years, int months, int days, int hours, int minutes, int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nodeDate);
        calendar.add(Calendar.SECOND, seconds);
        calendar.add(Calendar.MINUTE, minutes);
        calendar.add(Calendar.HOUR, hours);
        calendar.add(Calendar.DATE, days);
        calendar.add(Calendar.MONTH, months);
        calendar.add(Calendar.YEAR, years);

        return calendar.getTime();
    }

    // 计算指定时间的之前或之后多久时间(获取目标时间-值代表之前，+值代表之后)
    public static Date increasedSeconds(Date nodeDate,int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nodeDate);
        calendar.add(Calendar.SECOND, seconds);
        return calendar.getTime();
    }

    //获取两个时间之间的天数
    public static int getDatePoor(Date endDate, Date nowDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(endDate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(nowDate);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);
        int parseInt = Integer.parseInt(String.valueOf(between_days));
        parseInt = parseInt + 1;
        return parseInt;
    }
    /**
     * 获取 2 个时间的自然年历的时间间隔
     *
     * @param nextDate     后面的时间，需要大于 previousDate
     * @param previousDate 前面的时间
     * @return [年, 月, 日, 小时, 分钟, 秒]的数组
     */
    public static int[] getTimeIntervalArray(Calendar nextDate, Calendar previousDate) {
        int year = nextDate.get(Calendar.YEAR) - previousDate.get(Calendar.YEAR);
        int month = nextDate.get(Calendar.MONTH) - previousDate.get(Calendar.MONTH);
        int day = nextDate.get(Calendar.DAY_OF_MONTH) - previousDate.get(Calendar.DAY_OF_MONTH);
        int hour = nextDate.get(Calendar.HOUR_OF_DAY) - previousDate.get(Calendar.HOUR_OF_DAY);// 24小时制
        int min = nextDate.get(Calendar.MINUTE) - previousDate.get(Calendar.MINUTE);
        int second = nextDate.get(Calendar.SECOND) - previousDate.get(Calendar.SECOND);

        boolean hasBorrowDay = false;// "时"是否向"天"借过一位

        if (second < 0) {
            second += 60;
            min--;
        }

        if (min < 0) {
            min += 60;
            hour--;
        }

        if (hour < 0) {
            hour += 24;
            day--;

            hasBorrowDay = true;
        }

        if (day < 0) {
            // 计算截止日期的上一个月有多少天，补上去
            Calendar tempDate = (Calendar) nextDate.clone();
            tempDate.add(Calendar.MONTH, -1);// 获取截止日期的上一个月
            day += tempDate.getActualMaximum(Calendar.DAY_OF_MONTH);

            // nextDate是月底最后一天，且day=这个月的天数，即是刚好一整个月，比如20160131~20160229，day=29，实则为1个月
            if (!hasBorrowDay
                    && nextDate.get(Calendar.DAY_OF_MONTH) == nextDate.getActualMaximum(Calendar.DAY_OF_MONTH)// 日期为月底最后一天
                    && day >= nextDate.getActualMaximum(Calendar.DAY_OF_MONTH)) {// day刚好是nextDate一个月的天数，或大于nextDate月的天数（比如2月可能只有28天）
                day = 0;// 因为这样判断是相当于刚好是整月了，那么不用向 month 借位，只需将 day 置 0
            } else {// 向month借一位
                month--;
            }
        }

        if (month < 0) {
            month += 12;
            year--;
        }

        return new int[]{year, month, day, hour, min, second};
    }

    /**
     *根据住院时间和生日计算时间
     * @param ageDTO
     * @return
     */
    public static String getAge(AgeDTO ageDTO){
        if(StringUtils.isNoneBlank(ageDTO.getInDateTime(),ageDTO.getBirthday())){
            Calendar c1 = Calendar.getInstance();
            c1.setTime(DateUtil.stringToDate(ageDTO.getBirthday()));
            Calendar c2 = Calendar.getInstance();
            c2.setTime(DateUtil.stringToDate(ageDTO.getInDateTime()));
            int[] times = DateUtil.getTimeIntervalArray(c2, c1);
            int years = times[0];
            int months = times[1];
            int days = times[2];
            int hours = times[3];
            int minutes = times[4];
            if (years >= 3) {
                return  years + "岁";
            } else if (years >= 1) {
                return years + "岁" + (months == 0 ? "" : months + "月");
            } else if (months >= 1) {
                return months + "月" + (days == 0 ? "" : days + "天");
            } else if (days >= 1) {
                return  days + "天";
            } else if (hours >= 1) {
                return hours + "小时" + (minutes == 0 ? "" : minutes + "分钟");
            } else if (minutes >= 0) {
                return  minutes + "分钟";
            } else {
                return  (years == 0 ? "" : years + "岁") + (months == 0 ? "" : months + "月") + (days == 0 ? "" : days + "天") + (hours == 0 ? "" : hours + "小时") + (minutes == 0 ? "" : minutes + "分钟");
            }
        }else{
            final String defaultValue="0";
            if(StringUtils.isBlank(ageDTO.getAgeDay())){
                ageDTO.setAgeMonth(defaultValue);
                ageDTO.setAgeYear(defaultValue);
                ageDTO.setAgeDay(defaultValue);
                ageDTO.setAgeHour(defaultValue);
                ageDTO.setAgeMinute(defaultValue);
            }
            // 判断天是否为空
            if (defaultValue.equals(ageDTO.getAgeDay())) {
               String year=defaultValue.equals(ageDTO.getAgeYear())?"":ageDTO.getAgeYear()+"岁";
               String month=defaultValue.equals(ageDTO.getAgeMonth())?"":ageDTO.getAgeMonth()+"月";
               return year+month;
            } else {
                // 判断分钟是否为空
                if (defaultValue.equals(ageDTO.getAgeMinute())) {
                  String age= (
                          (
                              (defaultValue.equals(ageDTO.getAgeYear()) ? "" : ageDTO.getAgeYear() + "岁")
                             +(defaultValue.equals(ageDTO.getAgeMonth()) ? "" : ageDTO.getAgeMonth() + "月")
                             +(defaultValue.equals(ageDTO.getAgeDay()) ? "" : ageDTO.getAgeDay() + "天")
                          ) == null ? "0分钟" :
                                  (
                                          (defaultValue.equals(ageDTO.getAgeYear()) ? "" : ageDTO.getAgeYear() + "岁")
                                                  + (defaultValue.equals(ageDTO.getAgeMonth()) ? "" : ageDTO.getAgeMonth() + "月")
                                                  + (defaultValue.equals(ageDTO.getAgeDay()) ? "" : ageDTO.getAgeDay() + "天")
                                  )
                  );
                  if(StringUtils.isBlank(age)){
                      age= defaultValue;
                  }
                  return  age;
                } else {
                    if(StringUtils.isEmpty(ageDTO.getAgeMinute())) {
                        ageDTO.setAgeMinute("0");
                    }
                    int days = Integer.parseInt(ageDTO.getAgeMinute()) / 60 / 24;
                    int hour = Integer.parseInt(ageDTO.getAgeMinute()) / 60 % 24;
                    String age = (days == 0 ? (hour == 0 ? "" : hour + "小时") : days + "天");
                    if (StringUtils.isBlank(age)) {
                        age = defaultValue;
                    }
                    return age;
                }
            }
        }

    }




    /**
     * 得到几天前的时间
     * @param date
     * @param day
     * @return
     */
    public static Date getDateBefore(Date date,int day){
        Calendar now =Calendar.getInstance();
        now.setTime(date);
        now.set(Calendar.DATE,now.get(Calendar.DATE)-day);
        return now.getTime();
    }

    /**
     * 得到几天后的时间
     * @param date
     * @param day
     * @return
     */
    public static Date getDateAfter(Date date,int day){
        Calendar now =Calendar.getInstance();
        now.setTime(date);
        now.set(Calendar.DATE,now.get(Calendar.DATE)+day);
        return now.getTime();
    }

    /**
     * 得到几天后的时间
     * @param date
     * @param second
     * @return
     */
    public static Date getDateAfterRedSecond(Date date,int second){
        Calendar now =Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.SECOND,-second);
        return now.getTime();
    }

    /**
     * LocalDateTime转换为Date
     * @param localDateTime
     */
    public static Date localDateTime2Date( LocalDateTime localDateTime){
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

}
